/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: skahl $
 * $Revision: 1.7 $
 * $Date: 2007/12/04 04:41:22 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.adapters;

import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import au.edu.educationau.opensource.dsm.DeusExMachina;
import au.edu.educationau.opensource.dsm.adapters.contenthandler.OpenSearchContentHandler;
import au.edu.educationau.opensource.dsm.cache.DiskCacheEntry;
import au.edu.educationau.opensource.dsm.obj.SearchCriteria;
import au.edu.educationau.opensource.dsm.util.StringUtils;
import au.edu.educationau.opensource.dsm.worker.ResultSetUnifier;

/**
 * Generic OpenSearchAdapter. Should handle the parameters that are common to
 * both dsm and open search.
 * 
 */

public class OpenSearchAdapterImpl extends SearchAdapter {

	static Logger logger = Logger.getLogger(OpenSearchAdapterImpl.class.getName());

	private int startValue = 1;

	private String newURL = "";

	/** Parent constructor */
	public OpenSearchAdapterImpl() {
		super();
	}

	/**
	 * See the SearchAdapter abstract method doPrime
	 * 
	 * @exception Throwable
	 */
	public void doPrime() throws Throwable {
		SearchCriteria criteria = super.getSearchCriteria();
		String url = this.getProperties().getSearchURL();
		int batchSize = this.getProperties().getBatchSize();
		String query = criteria.getQuery().replaceAll("\\s", " ");
		String phraseDelimiter = this.getProperties().getExtraProperty("opensearch.phrase.delimiter");
		String conjunctionDelimiter = this.getProperties().getExtraProperty("opensearch.conjunction.delimiter");
		String disjunctionDelimiter = this.getProperties().getExtraProperty("opensearch.disjunction.delimiter");

		if ("phrase".equals(criteria.getKeywordConstraint()) && phraseDelimiter != null) {
			// add delimiters for phrase search
			query = phraseDelimiter + query + phraseDelimiter;
		} else if ("all".equals(criteria.getKeywordConstraint()) && conjunctionDelimiter != null) {
			// add delimiters for AND search
			query = StringUtils.arrayToString(criteria.getQueryArray(), " " + conjunctionDelimiter + " ");
		} else if ("any".equals(criteria.getKeywordConstraint()) && disjunctionDelimiter != null) {
			// add delimiters for OR search
			query = StringUtils.arrayToString(criteria.getQueryArray(), " " + disjunctionDelimiter + " ");
		}
		// format url according to configuration
		this.newURL = getFormattedUrl(url, query, batchSize);

		clearURLBuffer();

	}

	protected String getFormattedUrl(String url, String query, int batchSize) {
		try {
			query = URLEncoder.encode(query, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			logger.warn("Failed to encode query param.", e);
		}
		return MessageFormat.format(url, new Object[] { query, new Integer(batchSize) });
	}

	/**
	 * See the SearchAdapter abstract method doPerform
	 * 
	 * @exception Throwable
	 */
	public ArrayList doPerform() throws Throwable {
		OpenSearchContentHandler eCHandler = newContentHandler();
		eCHandler.setSearchAdapterProperties(super.getProperties());
		eCHandler.setSearchCriteria(super.getSearchCriteria());
		DiskCacheEntry entry = DeusExMachina._DiskCache().getEntry(this.newURL, "UTF8");

		if (null != entry) {
			Reader reader = entry.getReader("UTF8");

			if (null != reader) {
				eCHandler = (OpenSearchContentHandler) ResultSetUnifier.processXML(reader, eCHandler, "UTF-8");
			}
		}

		ArrayList batch = eCHandler.getResults();
		super.setTheoreticalAvailableResults(eCHandler.getFound());
		super.setDiagnosticCode(eCHandler.getDiagnosticCode());
		this.newURL = "";
		return batch;
	}

	protected OpenSearchContentHandler newContentHandler() {
		return new OpenSearchContentHandler();
	}

	/**
	 * See the SearchAdapter abstract method doNextBatch
	 * 
	 * @exception Throwable
	 */
	public boolean doNextBatch() throws Throwable {
		return false;
	}

	/**
	 * See the SearchAdapter abstract method doStopNice
	 * 
	 * @exception Throwable
	 */
	public void doStopNice() throws Throwable {
		// does nothing here
	}

	/**
	 * See the SearchAdapter abstract method doStopForce
	 * 
	 * @exception Throwable
	 */
	public void doStopForce() throws Throwable {
		// does nothing here
	}

	/** Class display string */
	public String toString() {
		return this.getClass().getName();
	}

	public String getNewURL() {
		return newURL;
	}
} // -- EOF
